package com.llbnk.srb.core.controller.api;


import com.alibaba.fastjson.JSON;
import com.llbnk.common.result.R;
import com.llbnk.srb.core.hfb.RequestHelper;
import com.llbnk.srb.core.service.UserAccountService;
import com.llbnk.srb.core.util.JwtUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Map;

/**
 * <p>
 * 用户账户 前端控制器
 * </p>
 *
 * @author llbnk
 * @since 2022-04-07
 */
@Api(tags = "会员账户")
@RestController
@RequestMapping("/api/core/userAccount")
@Slf4j
public class UserAccountController {

    @Resource
    private UserAccountService userAccountService;

    @ApiOperation("充值")
    @PostMapping("/auth/commitCharge/{chargeAmt}")
    public R commitCharge(
            @ApiParam(value = "充值金额", required = true)
            @PathVariable BigDecimal chargeAmt, HttpServletRequest request) {

        String token = request.getHeader("token");
        Long userId = JwtUtils.getUserId(token);
        String formStr = userAccountService.commitCharge(chargeAmt, userId);
        return R.ok().data("formStr", formStr);
    }

    @ApiOperation(value = "用户充值异步回调")
    @PostMapping("/notify")//这个地址必须与你commitCharge方法发送的回调URL保持一致
    public String notify(HttpServletRequest request) {
        //将从hfb接受过来的参数，是hfb手册3.9.3中表格所写的回调参数
        Map<String, Object> paramMap = RequestHelper.switchMap(request.getParameterMap());
        log.info("用户充值异步回调：" + JSON.toJSONString(paramMap));

        /**
         * 下面就是验签过程，假如验签不等，直接返回false此时hfb一定会再次请求（hfb设置一共重试5次）
         * 直到srb返回success结束业务。
         * resultCode结果编码代表的是当前srb在hfb下的编码（因为第三方平台不可能就一个p2p平台业务）
         * 所以需要校验是否结果编码相同。
         * 如果结果编码一致，就做同步数据。如果不一致，说明远程hfb充值失败了！（和srb无关），因为hfb
         * 都已经业务充值是吧，如果你回fail就是想让hfb重试，已经失败了就不必重试了。
         *
         * 当hfb发给srb数据，在srb回数据的时候发生错误，结果hfb并没有收到回复信息，造成了hfb充值成功，
         * srb也同步成功，但由于网络原因（超时），hfb没收到srb回的消息。于是hfb又申请了，于是在srb
         * 中又加了一次金额，但是hfb中并没有添加这次金额，于是财富自由啦~
         *
         * 这种情况叫做接口没有满足幂等问题
         *
          */

        //校验签名
        if(RequestHelper.isSignEquals(paramMap)) {
            //充值成功交易
            if("0001".equals(paramMap.get("resultCode"))) {
                return userAccountService.notify(paramMap);
            } else {
                log.info("用户充值异步回调充值失败：" + JSON.toJSONString(paramMap));
                return "success";
            }
        } else {
            log.info("用户充值异步回调签名错误：" + JSON.toJSONString(paramMap));
            return "fail";
        }
    }

    @ApiOperation("查询账户余额")
    @GetMapping("/auth/getAccount")
    public R getAccount(HttpServletRequest request){
        String token = request.getHeader("token");
        Long userId = JwtUtils.getUserId(token);
        BigDecimal account = userAccountService.getAccount(userId);
        return R.ok().data("account", account);
    }

    @ApiOperation("用户提现")
    @PostMapping("/auth/commitWithdraw/{fetchAmt}")
    public R commitWithdraw(
            @ApiParam(value = "金额", required = true)
            @PathVariable BigDecimal fetchAmt, HttpServletRequest request) {

        String token = request.getHeader("token");
        Long userId = JwtUtils.getUserId(token);
        String formStr = userAccountService.commitWithdraw(fetchAmt, userId);
        return R.ok().data("formStr", formStr);
    }

    @ApiOperation("用户提现异步回调")
    @PostMapping("/notifyWithdraw")
    public String notifyWithdraw(HttpServletRequest request) {
        Map<String, Object> paramMap = RequestHelper.switchMap(request.getParameterMap());
        log.info("提现异步回调：" + JSON.toJSONString(paramMap));

        //校验签名
        if(RequestHelper.isSignEquals(paramMap)) {
            //提现成功交易
            if("0001".equals(paramMap.get("resultCode"))) {
                userAccountService.notifyWithdraw(paramMap);
            } else {
                log.info("提现异步回调充值失败：" + JSON.toJSONString(paramMap));
                return "fail";
            }
        } else {
            log.info("提现异步回调签名错误：" + JSON.toJSONString(paramMap));
            return "fail";
        }
        return "success";
    }

}

